package org.loong.crypto.service.core.provider;

import org.loong.crypto.common.exception.CryptoException;
import org.loong.crypto.core.algorithm.CipherAlgorithm;
import org.loong.crypto.core.algorithm.HmacAlgorithm;
import org.loong.crypto.core.algorithm.KeyAlgorithm;
import org.loong.crypto.core.algorithm.KeyPairAlgorithm;
import org.loong.crypto.core.algorithm.MessageDigestAlgorithm;
import org.loong.crypto.core.algorithm.SignatureAlgorithm;
import org.loong.crypto.core.params.CipherParameters;
import org.loong.crypto.core.params.HmacParameters;
import org.loong.crypto.core.params.MessageDigestParameters;
import org.loong.crypto.core.params.SignatureParameters;

/**
 * Signer factory to create a signer.
 */
public interface ProviderFactory {

    /**
     * Create a random based on the algorithm.
     * 
     * @return {@link RandomGenerator}
     * @throws the {@link CryptoException}
     */
    RandomGenerator createRandomGenerator() throws CryptoException;
    
    /**
     * Create a key based on the algorithm.
     * 
     * @param algorithm the key algorithm
     * @return {@link KeyGenerator}
     * @throws the {@link CryptoException}
     */
    KeyGenerator createKeyGenerator(KeyAlgorithm algorithm) throws CryptoException;

    /**
     * Create a key pair based on the algorithm.
     * 
     * @param algorithm the key pair algorithm
     * @return {@link KeyPairGenerator}
     * @throws the {@link CryptoException}
     */
    KeyPairGenerator createKeyPairGenerator(KeyPairAlgorithm algorithm) throws CryptoException;

    /**
     * Create a message digest based on the algorithm.
     * 
     * @param algorithm the message digest algorithm
     * @param params the message digest parameters ${@link MessageDigestParameters}
     * @return {@link MessageDigest}
     * @throws the {@link CryptoException}
     */
    MessageDigest createMessageDigest(MessageDigestAlgorithm algorithm, MessageDigestParameters params) throws CryptoException;

    /**
     * Create a hmac signer based on the algorithm and params.
     * 
     * @param algorithm the hmac algorithm
     * @param params the hmac parameters ${@link HmacParameters}
     * @return {@link HmacSigner}
     * @throws the {@link CryptoException}
     */
    HmacSigner createHmacSigner(HmacAlgorithm algorithm, HmacParameters params) throws CryptoException;

    /**
     * Create a hmac verifier based on the algorithm and params.
     * 
     * @param algorithm the hmac algorithm
     * @param params the hmac parameters ${@link HmacParameters}
     * @return {@link HmacVerifier}
     * @throws the {@link CryptoException}
     */
    HmacVerifier createHmacVerifier(HmacAlgorithm algorithm, HmacParameters params) throws CryptoException;

    /**
     * Create a encrypter based on the algorithm and params.
     * 
     * @param algorithm the cipher algorithm
     * @param params the cipher parameters ${@link CipherParameters}
     * @return {@link Encrypter}
     * @throws the {@link CryptoException}
     */
    Encrypter createEncrypter(CipherAlgorithm algorithm, CipherParameters params) throws CryptoException;

    /**
     * Create a decrypter based on the algorithm and params.
     * 
     * @param algorithm the cipher algorithm
     * @param params the cipher parameters ${@link CipherParameters}
     * @return {@link Encrypter}
     * @throws the {@link CryptoException}
     */
    Decrypter createDecrypter(CipherAlgorithm algorithm, CipherParameters params) throws CryptoException;
    
    /**
     * Create a signer based on the algorithm and params.
     * 
     * @param algorithm the signature algorithm
     * @param params the signature parameters ${@link SignatureParameters}
     * @return {@link Signer}
     * @throws the {@link CryptoException}
     */
    Signer createSigner(SignatureAlgorithm algorithm, SignatureParameters params) throws CryptoException;

    /**
     * Create a verifier based on the algorithm and params.
     * 
     * @param algorithm the signature algorithm
     * @param params the signature parameters ${@link SignatureParameters}
     * @return {@link Verifier}
     * @throws the {@link CryptoException}
     */
    Verifier createVerifier(SignatureAlgorithm algorithm, SignatureParameters params) throws CryptoException;
}
